package geppetto.phraseHMM;


import geppetto.cat.alignments.AlignmentEvaluator;
import geppetto.cat.alignments.AlignmentStats;
import geppetto.cat.alignments.AlignmentsSet;
import geppetto.cat.alignments.AlignmentEvaluator.Evaluation;
import geppetto.cat.constrains.BijectivityConstrains;
import geppetto.cat.constrains.ConstrainedProjectionStats;
import geppetto.cat.constrains.SentenceConstrainedProjectionStats;
import geppetto.cat.corpus.BilingualCorpus;
import geppetto.cat.models.SparseTranslationTable;
import geppetto.cat.models.stats.EStepStats;

import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;




public class BijectiveM1 extends IBMM1{

	BijectivityConstrains constrains;
	double _epsilon;
	double _slack;
	int _maxStepSize; 
	int _maxNumberIterations;
	public BijectiveM1(BilingualCorpus corpus, double smoothing,
			double epsilon, double slack,
			int maxStepSize, int maxNumberProjectionIterations) {
		this(corpus, null,smoothing, epsilon,slack,maxStepSize,maxNumberProjectionIterations);
	}

	public BijectiveM1(BilingualCorpus corpus, SparseTranslationTable tt, double smoothing, 
			double epsilon, double slack,
			int maxStepSize, int maxNumberProjectionIterations) {
		super(corpus, tt,smoothing);
		_epsilon = epsilon;
		_slack = slack;
		_maxStepSize = maxStepSize;
		_maxNumberIterations = maxNumberProjectionIterations;
	}

	
	BijectiveM1(){
			
	}
	public String getName() {
		return "Bijective Constrain M1";
	}
	
	public SentenceConstrainedProjectionStats projectPosteriors(){
		double[] b = new double[_sourceSentenceIDS.length];
		java.util.Arrays.fill(b, 1);
		 return new BijectivityConstrains(this,_epsilon,_slack,_maxStepSize,_maxNumberIterations,b).steepestAscentProjection();
	}

	public EStepStats createModelStats(){
		ConstrainedProjectionStats pstats = new ConstrainedProjectionStats();
		EStepStats stats = new EStepStats();
		stats.pstats = pstats;
		return stats;
	}
	
	public static void main(String[] args) throws IOException {
		String corpusDescription = args[0];
		int size = Integer.parseInt(args[1]); 
		int maxSentenceSize = Integer.parseInt(args[2]); 
		int numberIterations = Integer.parseInt(args[3]); 
		double smoothing = Double.parseDouble(args[4]);
		double epsilon = Double.parseDouble(args[5]); 
		double slack = Double.parseDouble(args[6]); 
		int maxStepSize = Integer.parseInt(args[7]);
		int maxProjectionNumberIterations = Integer.parseInt(args[8]);
		String baseOutput = args[9];
		String outputFile = args[10];
		boolean trainWithResults = Boolean.parseBoolean(args[11]);
		int numberIterationsWithResults = Integer.parseInt(args[12]);
		String saveModelDir = args[13];
		// System.out.println("Corpus "+corpusName);
		System.out.println("Size " + size);
		System.out.println("Max Sentence size " + maxSentenceSize);
		System.out.println("Number of iterations " + numberIterations);
		System.out.println("Smoothing " + smoothing);
		System.out.println("Epsilon " + epsilon);
		System.out.println("Slack " + slack);
		System.out.println("Max Step Size" + maxStepSize);
		System.out.println("Max Number of Iterations" + maxProjectionNumberIterations);
		System.out.println("BaseOutpup " + baseOutput);
		System.out.println("OutputFile " + outputFile);
		System.out.println("Train with results " + trainWithResults);
		System.out.println("Number of Iterations with results "
				+ numberIterationsWithResults);

		BilingualCorpus corpus = BilingualCorpus.getCorpusFromFileDescription(
				corpusDescription, size, maxSentenceSize);

		BilingualCorpus revCorpus = corpus.reverse();

		BijectiveM1 m1 = new BijectiveM1(corpus,smoothing,epsilon,slack,maxStepSize,maxProjectionNumberIterations);
		BijectiveM1 m1b = new BijectiveM1(revCorpus,smoothing,epsilon,slack,maxStepSize,maxProjectionNumberIterations);
		
		if (!trainWithResults) {
			m1.train(numberIterations,false,"");
			m1b.train(numberIterations,false,"");
		} else {
			
//			ArrayList<Evaluation[]> evalsList = m1.trainWithResults(
//					numberIterationsWithResults, BilingualCorpus.DEV_CORPUS,false,"");
//			ArrayList<Evaluation[]> evalsListb = m1b.trainWithResults(
//					numberIterationsWithResults, BilingualCorpus.DEV_CORPUS,false,"");
//			System.out.println("Viterbi all");
//			Evaluation[] evals = evalsList.get(0);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
//			System.out.println("Viterbi Rare");
//			evals = evalsList.get(1);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
//			System.out.println("Viterbi Common");
//			evals = evalsList.get(2);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
//			
//			System.out.println("Precision all");
//			 evals = evalsList.get(3);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
//			System.out.println("Precision Rare");
//			evals = evalsList.get(4);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
//			System.out.println("Precision Common");
//			evals = evalsList.get(5);
//			for (int i = 0; i < evals.length; i++) {
//				System.out.println("Iter " + i + evals[i]);
//			}
//			System.out.println(" ----- ");
			
					
		}

		
		System.out.println("Without decoding");
		
		
		float treshold = m1.tuneTreshholdAER(BilingualCorpus.DEV_CORPUS,false);
		AlignmentsSet sa2 = m1.posteriorAlignments(
				BilingualCorpus.TEST_CORPUS, treshold,false,false);
		Evaluation eval22 = AlignmentEvaluator.evaluate(sa2, corpus.getGold());
		System.out.println("Forward Posterioir decoding no projection" + eval22);

		
		float tresholdb = m1b.tuneTreshholdAER(BilingualCorpus.DEV_CORPUS,false);
		AlignmentsSet sa2b = m1b.posteriorAlignments(
				BilingualCorpus.TEST_CORPUS, tresholdb,false,false);
		Evaluation eval22b = AlignmentEvaluator.evaluate(sa2b, revCorpus.getGold());
		System.out.println("Backward  Posterioir decoding no projection" + eval22b);
		
		getCurves(corpus, BilingualCorpus.TEST_CORPUS, false, m1, "fnp");
		getCurves(revCorpus, BilingualCorpus.TEST_CORPUS, false, m1b, "bnp");
		
		System.out.println("With decoding");
		
		
		treshold = m1.tuneTreshholdAER(BilingualCorpus.DEV_CORPUS,true);
		sa2 = m1.posteriorAlignments(
				BilingualCorpus.TEST_CORPUS, treshold,true,true);
		eval22 = AlignmentEvaluator.evaluate(sa2, corpus.getGold());
		System.out.println("Forward Posterioir decoding with projection" + eval22);

		
		tresholdb = m1b.tuneTreshholdAER(BilingualCorpus.DEV_CORPUS,true);
		sa2b = m1b.posteriorAlignments(
				BilingualCorpus.TEST_CORPUS, tresholdb,true,true);
		eval22b = AlignmentEvaluator.evaluate(sa2b, revCorpus.getGold());
		System.out.println("Backward  Posterioir decoding with projection" + eval22b);
	
		getCurves(corpus, BilingualCorpus.TEST_CORPUS, true,m1, "fbp");
		getCurves(revCorpus, BilingualCorpus.TEST_CORPUS, true, m1b, "bbp");
		
		
	}
}
